import {
  ConflictException,
  Injectable,
  InternalServerErrorException,
  NotFoundException,
} from '@nestjs/common';
import { CreateRoleDto } from './dto/create-role.dto';
import { UpdateRoleDto } from './dto/update-role.dto';
import { User } from '../user/entities/user.entity';
import { EntityManager, Repository } from 'typeorm';
import { Role } from './entities/role.entity';
import { InjectRepository } from '@nestjs/typeorm';
import * as moment from 'moment';
import { ThemeFilterDto } from '../theme/dto/themeFilterDto';
import { IPaginationOptions, paginate, Pagination } from '../utils/paginate';
import { BindUserDto } from './dto/bind-user.dto';

@Injectable()
export class RoleService {
  constructor(
    @InjectRepository(Role)
    private repository: Repository<Role>,
    private entityManager: EntityManager,
  ) {}
  async create(createRoleDto: CreateRoleDto, user: User): Promise<string> {
    const { name } = createRoleDto;
    const serial = 'WIT' + moment().unix();
    const role = this.repository.create({ name, serial, user });
    try {
      await this.repository.save(role);
    } catch (error) {
      if (error.code === '23505' || error.code === 'ER_DUP_ENTRY') {
        // 重复用户名
        throw new ConflictException('该数据已存在！');
      } else {
        throw new InternalServerErrorException('内部服务器错误异常');
      }
    }
    return '创建成功！';
  }

  async findAll(
    data: ThemeFilterDto,
    options: IPaginationOptions,
  ): Promise<Pagination<Role>> {
    const { search: name } = data;
    let roles = this.repository
      .createQueryBuilder('role')
      .leftJoinAndSelect('role.menu', 'menu');
    if (name) {
      roles = roles.andWhere(
        'LOWER(role.name) LIKE LOWER(:name) OR LOWER(role.serial) LIKE LOWER(:name)',
        {
          name: `%${name}%`,
        },
      );
    }
    roles
      // .leftJoinAndSelect('menu.children', 'children')
      .andWhere('role.isDelete = 0');
    return await paginate<Role>(roles, options);
  }

  async findOne(id: string): Promise<Role> {
    const found = await this.repository
      .createQueryBuilder('role')
      .where({ id, isDelete: 0 })
      .leftJoinAndSelect('role.menu', 'menu')
      .getOne();
    if (!found) {
      throw new NotFoundException(`参数${id}没有找到！`);
    }
    return found;
  }

  async update(updateRoleDto: UpdateRoleDto, user: User): Promise<string> {
    const { name, id, isDelete } = updateRoleDto;
    const role = await this.findOne(id);
    if (!role) {
      throw new NotFoundException(`参数 ${id} 没有找到！`);
    }
    if (name) role.name = name;
    if (isDelete) role.isDelete = isDelete;
    await this.repository.save(role);
    return '修改成功！';
  }

  async remove(id: string) {
    const result = await this.repository.delete({ id });
    if (result.affected === 0) {
      throw new NotFoundException(`参数 ${id} 没有找到！`);
    }
    return `删除成功!`;
  }

  async bindUsers(data: BindUserDto): Promise<string> {
    const { userId, roleId } = data;
    const roles = await this.repository.findOneBy({ id: roleId });
    const user = await this.entityManager
      .getRepository(User)
      .findOneBy({ id: userId });
    user.roles = roles;
    await this.entityManager.getRepository(User).save(user);
    return '绑定角色成功！';
  }
}
